package edu.core.testapp.server;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;

import javax.xml.bind.DatatypeConverter;

import protect03.CloseKey;
import protect03.ElGamal;
import protect03.KeyHolder;
import protect03.OpenKey;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import edu.core.testapp.client.Protect03Service;
import edu.core.testapp.shared.ElGamalKeyHolder;

@SuppressWarnings("serial")
public class Protect03ServiceImpl extends RemoteServiceServlet implements
		Protect03Service {

	@Override
	public ElGamalKeyHolder generateKeys() {
		
		KeyHolder kh = ElGamal.generateKeys(BigInteger.TEN.pow(20), BigInteger.TEN.pow(10));
		
		return convert(kh);
	}

	@Override
	public String encodeBase64(String base64, ElGamalKeyHolder keys) throws IOException {
		
		byte[] original = DatatypeConverter.parseBase64Binary(base64);
		
		ByteArrayInputStream bais = new ByteArrayInputStream(original);
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		ElGamal.encode(convert(keys).getOpenKey(), bais, baos);
		
		byte[] encoded = baos.toByteArray();
		
		return DatatypeConverter.printBase64Binary(encoded);
	}

	@Override
	public String decodeBase64(String base64, ElGamalKeyHolder keys) throws IOException {

		byte[] encoded = DatatypeConverter.parseBase64Binary(base64);
		
		ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		ElGamal.decode(convert(keys).getOpenKey(), convert(keys).getCloseKey(), bais, baos);
		
		byte[] original  = baos.toByteArray();
		
		return DatatypeConverter.printBase64Binary(original);
	}
	
	private static ElGamalKeyHolder convert(KeyHolder keys) {

		return new ElGamalKeyHolder(
				new ElGamalKeyHolder.OpenKey(
						keys.getOpenKey().getP().toString(), 
						keys.getOpenKey().getG().toString(), 
						keys.getOpenKey().getY().toString()
						),
				new ElGamalKeyHolder.CloseKey(
						keys.getCloseKey().getX().toString()
						)
				);
	}
	
	private static KeyHolder convert(ElGamalKeyHolder keys) {
		
		return new KeyHolder(
				new OpenKey(
						new BigInteger(keys.getOpenKey().getP()),
						new BigInteger(keys.getOpenKey().getG()),
						new BigInteger(keys.getOpenKey().getY())
						),
				new CloseKey(
						new BigInteger(keys.getCloseKey().getX())
						)
				);
	}

}
